package com.hzmg.akka.utils;

import akka.actor.ActorSelection;
import akka.actor.ActorSystem;
import akka.actor.Address;
import akka.actor.AddressFromURIString;
import akka.pattern.Patterns;
import com.google.common.collect.Maps;
import com.hzmg.common.exception.AkkaCloudException;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import org.checkerframework.checker.units.qual.A;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Duration;
import java.util.Map;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;

/**
 * 远程调用工具
 *
 * @author zbw
 * @since 2022/8/14
 */
public class RemoteCallUtils {
    private static final Logger logger = LoggerFactory.getLogger(RemoteCallUtils.class);
    private static final String AKKA_NODE_PATH = "akka://%s@%s/user/%s";
    public static Object getRemoteService(Object parameters, String actorName, String remoteServerName) {
        //这步正式使用时换成获取已有的actorSystem
        //加载resources里的配置文件，里面包含AcotrSystem创建所需参数，
        //设置工作端口，序列化方式，日志级别
        String actorSystemAddress;
        Map<String, Object> overrideConfig = Maps.newHashMap();
        String localIP = NetUtils.getLocalHost();
        overrideConfig.put("akka.remote.artery.canonical.hostname", localIP);
        overrideConfig.put("akka.remote.artery.canonical.port", "10086");
        actorSystemAddress = localIP + ":" + "10086";
        Config akkaBasicConfig = ConfigFactory.load("hzmg-server.akka.conf");
        Config akkaFinalConfig = ConfigFactory.parseMap(overrideConfig).withFallback(akkaBasicConfig);

        //创建Actor工厂
        ActorSystem actorSystem = ActorSystem.create("akka-server", akkaFinalConfig);
        //通过Actor工厂创建Actor,
        // 第一个参数为创建Actor时指定选项的配置类,第二个参数指定该Actor的名称，
        //通过该Actor名称与ActorSystem名称，
        //可以构建出路径: akka://hzmg-server/ip/friend_actor，
        //根据该路径找到actor进行通信
        //开始通信
        //正式版将会改成从注册中心获取对应服务信息并拼接
        /*String path = "akka://%s/@172.31.160.1:10087/user/appName=%s";

        String realUrl = String.format(url, server, appName);
        String actorPath = "akka://remote-call@172.31.160.1:10087/user/helloRemote";*/
        //测试时一定要记得修改ip
        String actorRealPath=String.format(AKKA_NODE_PATH,remoteServerName,"172.28.176.1:10087",actorName);
        ActorSelection actorSelection = actorSystem.actorSelection(actorRealPath);

        CompletionStage<Object> askCS = Patterns.ask(actorSelection, parameters, Duration.ofMillis(11111));
        try {
            return (Object) askCS.toCompletableFuture().get(11111, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            throw new AkkaCloudException(e.toString());
        }
    }
    //异步非阻塞调用远程服务
    public static CompletionStage<Object> getRemoteServiceNio(Object parameters, String actorName, String remoteServerName) {
        //这步正式使用时换成获取已有的actorSystem
        //加载resources里的配置文件，里面包含AcotrSystem创建所需参数，
        //设置工作端口，序列化方式，日志级别
        String actorSystemAddress;
        Map<String, Object> overrideConfig = Maps.newHashMap();
        String localIP = NetUtils.getLocalHost();
        overrideConfig.put("akka.remote.artery.canonical.hostname", localIP);
        overrideConfig.put("akka.remote.artery.canonical.port", "10086");
        actorSystemAddress = localIP + ":" + "10086";
        Config akkaBasicConfig = ConfigFactory.load("hzmg-server.akka.conf");
        Config akkaFinalConfig = ConfigFactory.parseMap(overrideConfig).withFallback(akkaBasicConfig);

        //创建Actor工厂
        ActorSystem actorSystem = ActorSystem.create("akka-server", akkaFinalConfig);
        //通过Actor工厂创建Actor,
        // 第一个参数为创建Actor时指定选项的配置类,第二个参数指定该Actor的名称，
        //通过该Actor名称与ActorSystem名称，
        //可以构建出路径: akka://hzmg-server/ip/friend_actor，
        //根据该路径找到actor进行通信
        //开始通信
        //正式版将会改成从注册中心获取对应服务信息并拼接
        /*String path = "akka://%s/@172.31.160.1:10087/user/appName=%s";

        String realUrl = String.format(url, server, appName);
        String actorPath = "akka://remote-call@172.31.160.1:10087/user/helloRemote";*/
        //测试时一定要记得修改ip
        String actorRealPath=String.format(AKKA_NODE_PATH,remoteServerName,"172.28.176.1:10087",actorName);
        ActorSelection actorSelection = actorSystem.actorSelection(actorRealPath);

        return Patterns.ask(actorSelection, parameters, Duration.ofMillis(11111));

    }

}
